import sys
from pathlib import Path
from typing import IO
from warnings import warn

import click

from ..common import help_all
from ..panda import CompilerCmd
from ..panda_config import find_in_parents_build_bin_dir
from .update import Updater


class Context:
    def __init__(self, build_dir: Path):
        self.compiler = CompilerCmd(build_dir)

    @property
    def build_dir(self):
        return self.compiler.build_dir


context = click.make_pass_decorator(Context)


def _build_dir_default():
    return find_in_parents_build_bin_dir()


def option_build_dir(*param_decls: str):
    return click.option(
        *param_decls,
        help='The path to the panda build dir.',
        # default=_build_dir_default,
        type=click.Path(exists=True, dir_okay=True, path_type=Path),
        show_default=True,
    )


@click.group('error4test', invoke_without_command=True)
@option_build_dir('--build-dir')
@click.pass_context
@help_all()
def cli(ctx: click.Context, build_dir: Path | None):
    dir = build_dir or _build_dir_default()
    if not dir:
        click.echo('build-dir not found', err=True)
        ctx.exit(1)
    ctx.obj = Context(build_dir=dir.expanduser())


def _parse_filelist(filelist: IO[str]):
    for line in filelist:
        line = line.strip()
        if len(line) == 0 or line[0] == '#':
            continue
        path = Path(line)
        if path.exists():
            yield path
        else:
            warn(f'{path!s} file not exists.')


@cli.command(
    help='Update error list in ets-tests. If --filelist or --file not set then read filelist from STDIN',
)
@click.option(
    '--filelist',
    help='ETS tests filelist. If not specified, it is read from stdin.',
    type=click.Path(
        exists=True,
        file_okay=True,
        path_type=Path,
    ),
)
@click.option(
    '--file',
    '-f',
    type=click.Path(
        exists=True,
        file_okay=True,
        readable=True,
        path_type=Path,
    ),
    multiple=True,
)
@context
def update(ctx: Context, filelist: Path | None, file: list[Path] | None):
    files: list[Path] = []
    if not filelist and not file:
        files.extend(_parse_filelist(sys.stdin))
    if filelist:
        with filelist.open() as fp:
            files.extend(_parse_filelist(fp))
    if file:
        files.extend(file)
    Updater(panda=ctx.compiler).update_files(files)


if __name__ == '__main__':
    cli()
